/*
 * fichier : cltcp.c
 * auteur  : B. Abderrahmane & B. Damien
 * client TCP dans cltcp.c
 */

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include<fcntl.h>
#include<sys/stat.h>
#include <netinet/in.h>
#include <netdb.h>
#include<string.h>
#include<pthread.h>
#include<signal.h>

#define S_PORT 5000 

/*Déclaration des données*/
int sd;
int isCo=0;
struct sockaddr_in server;
pthread_t pserver;

/*Le serveur a déconnecté le client*/
void kick()
{
	if(isCo)
	{
		isCo=0;
		close(sd);
		printf("You have been kicked!\n");
	}
	else printf("Veuillez vous connecter!\n");
}

/*Procédure thread qui surveille les réponses du serveur*/
void *query()
{

	for(;;)
	{
		if(isCo)
		{
			char str[100]="";
			if(read(sd, str, sizeof(str))!=-1)
			{
				if(strcmp(str, "deconnexion")==0) kick();
				else printf("\nReponse server= %s\n", str);
			}
		}
	}
}

/*Procédure de connexion*/
void connexion()
{
	if(isCo)
	{ 
		printf("You are already connected!\n");
		return;
	}
	sd=socket(AF_INET,SOCK_STREAM,0);

	if(sd==-1) printf("Problème sd!\n");

	server.sin_addr.s_addr = inet_addr("127.0.0.1");
	server.sin_family = AF_INET;
	server.sin_port = htons(S_PORT);

	int nsd;
	nsd=connect(sd, (struct sockaddr *)&server, sizeof(server));
	if(nsd==-1)
		printf("Connexion impossible!\n");
	else
	{
		char name[100]="", response[100]="";
		char nameGrp[100]="", listGrp[2000]="";
		char newGrp[0];

		/*
		 * Demande du pseudonyme
		 */
		printf("User name: ");
		scanf("%s", name);
		write(sd, name, sizeof(name));

		/*
		 * Demande si l'utilisateur souhaite creer un groupe
		 */
		do
		{
			printf("New group ? (Y/N) : ");
			scanf("%s", newGrp);
		}
		while(newGrp[0]!='Y' && newGrp[0]!='y' && newGrp[0]!='N' && newGrp[0]!='n');
		
		/*
		 * Si nouveau groupe = Yes, demande nom du groupe et l'envoie au serveur
		 */
		if(newGrp[0]=='Y' || newGrp[0]=='y')
		{
			write(sd, "CREATE_GROUP", sizeof(char)*13);// indique au serveur que l'on souhaite creer un groupe
			printf("Group name: ");// demande le nom du groupe
			scanf("%s", nameGrp);
			write(sd, nameGrp, sizeof(nameGrp));//envoie le nom du groupe au serveur
			/*
			 * recuperation de la reponse du serveur
			 */
			if(read(sd, response, sizeof(response))!=-1) //lis la reponse du serveur
			{
				if(strcmp(response, "VALIDE_GROUP")==0) //traitement de la reponse : VALID_GROUP -> c'est OK
				{
					printf("Group created! Connection established!\n");
					isCo=1;
				}
				else if(strcmp(response, "INVALIDE_GROUP")==0) printf("Group name already chosen OR max user in group reached!\n");
				else printf("Erreur ReadValue() group\n");
			}
			else printf("Erreur Read() group\n");
		}
		else {
			write(sd, "JOIN_GROUP", sizeof(char)*13);// indique au serveur que l'on souhaite rejoindre un groupe
			if(read(sd, listGrp, sizeof(listGrp))==-1) printf("Erreur Read() list group\n");
			else printf("%s\n", listGrp);
			printf("Group name ");// demande le nom du groupe
			scanf("%s", nameGrp);
			write(sd, nameGrp, sizeof(nameGrp));
			if(read(sd, response, sizeof(response))!=-1) {
				if(strcmp(response, "GROUP_NAME_INVALIDE")==0)	printf("ERROR : NAME GROUP\n");
				else if(strcmp(response, "VALIDE_NAME")==0) {
					printf("You have been logged\n");
					isCo=1;
				}
				else if(strcmp(response, "INVALIDE_NAME")==0) printf("The name is already chosen OR The maximum number of user is reached!\n");
				else printf("Erreur ReadValue() name\n");
			}
			else printf("Erreur Read() name\n");
		     }
	}
}

/* ... de déconnexion */
void deconnexion()
{
	if(isCo)
	{
		write(sd, "deconnexion", sizeof(char)*11);
		isCo=0;
		close(sd);
	}
	else printf("Veuillez vous connecter!\n");
}

/* On envoit un message au serveur */
void writeServer()
{
	if(isCo)
	{
		char buff[100];
		printf("Message au serveur: ");
		scanf("%s", buff);
		write(sd, buff, sizeof(buff));
	}
	else printf("Veuillez vous connecter!\n");
}

/* Choix du menu */
void printAction(int *a)
{
	printf("Que voulez-vous faire?\n");
	printf("1: Connexion\n");	
	printf("2: Write\n");
	printf("3: Déconnexion\n");
	printf("Choix: ");
	scanf("%d", a);
}

/*Suivant le choix, on execute une action */
void action()
{	
	int a;
	printAction(&a);
	switch(a)
	{
		case 1:
			connexion();
			break;
		case 2:
			writeServer();
			break;
		case 3:
			deconnexion();
			break;
		default:
			printAction(&a);
			break;
	}
}

/*Signal lorsqu'on fait un ctrl+c, on se déconnecte proprement*/
void quit()
{
	write(sd, "deconnexion", sizeof(char)*11);
	close(sd);
	kill(getpid(), SIGKILL);
}

/*Programme principal du client*/
main(int argc, char *argv[])
{

int nbw, nbr;
signal(SIGINT, quit);

pthread_create(&pserver, NULL, query, NULL);

// ON boucle concernant les actions à faire
for(;;)
{
	action();
}

pthread_join(pserver, NULL);
close(sd);
}
